﻿using RabbitMQ.Client;
using RabbitMQ.Client.Events;

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

namespace RabbitMQClientCore
{
    public class RabbitMqClient
    {
        private static string mQueueName="";
        private static string mExChange="";
        private static string mRoutingKey = "";


        private static byte[] GetMsgByte(string msg) => Encoding.UTF8.GetBytes(msg);

        public static void SetExChange(string exChange)
        {
            mExChange = exChange;
        }

        public static void SetQueueName(string queueName)
        {
            mQueueName = queueName;
        }

        public static void SetRoutingKey(string rouingKey)
        {
            mRoutingKey = rouingKey;
        }

        #region 队列


        public static void ReceiveSimple(Action<string> action)
        {
            using (var connection = Mq.GetConnect())
            {
                using (var channel = connection.CreateModel())
                {
                    //创建队列
                    channel.QueueDeclare(queue: mQueueName, durable: false, exclusive: false, autoDelete: false, arguments: null);
                    //创建消费者（接受者）
                    var consumer = new EventingBasicConsumer(channel);
                    consumer.Received += (model, ea) =>
                    {
                        var message = Encoding.UTF8.GetString(ea.Body.ToArray());
                        action?.Invoke(message);

                        //手动签收，可以降低每次签收的性能损耗
                        channel.BasicAck(ea.DeliveryTag, false);
                    };

                    /*
                 * 消费消息
                 *  queue: 队列名称
                 *  autoAck: 是否自动回复Ack
                 *  consumerTag: 消费者标签，用来区分多个消费者
                 *  noLocal: 设置为true，表示不能将同一个Conenction中生产者发送的消息传递给这个Connection中的消费者
                 *  exclusive: 设置是否排他
                 *  arguments: 消费者的参数
                 *  consumer: 消费者
                 */
                    channel.BasicConsume(queue: mQueueName, autoAck: false, consumerTag: "jackttttta", noLocal: false, exclusive: false, arguments: null, consumer: consumer);

                    Console.ReadLine();
                }
            }
        }

        public static void SendSimple(string msg)
        {
            using (var connection = Mq.GetConnect())
            {
                using (var channel = connection.CreateModel())
                {
                    //创建队列
                    channel.QueueDeclare(queue: mQueueName, durable: false, exclusive: false, autoDelete: false, arguments: null);

                    channel.BasicReturn += (sender, args) =>
                    {
                        Console.WriteLine($"BasicReturn: {args.RoutingKey}->{Encoding.UTF8.GetString(args.Body.ToArray())}");
                    };
                    /*
                     * 发送消息
                     *  exchange: 交换机，为空表示使用默认的交换机
                     *  routingKey: 路由Key，默认的路由Key和队列名称完全一致
                     *  mandatory: 如果为true, 消息不能路由到指定的队列时，会触发channel.BasicReturn事件，如果为false，则broker会直接将消息丢弃
                     *  basicProperties: 消息属性
                     *  body: 消息内容
                     */
                    channel.BasicPublish(exchange: mExChange, routingKey: mQueueName, mandatory: false, basicProperties: null, body: GetMsgByte(msg));
                }
            }
        }

        #endregion

        #region 交换机

        public static void SendFanout(string msg)
        {
            using (var connection = Mq.GetConnect())
            {
                using (var channel = connection.CreateModel())
                {
                    channel.ExchangeDeclare(exchange: mExChange, type: ExchangeType.Fanout);

                    channel.QueueDeclare(queue: mQueueName, durable: false, exclusive: false, autoDelete: false, arguments: null);
                    channel.QueueBind(queue: mQueueName, exchange: mExChange, routingKey: mRoutingKey, arguments: null);

                    var message = GetMsgByte(msg);
                    channel.BasicPublish(exchange: mExChange,
                                         routingKey: mRoutingKey,
                                         basicProperties: null,
                                         body: message);
                }
            }
        }

        public static void ReceiveFanout(Action<string> action)
        {
            using (var connection = Mq.GetConnect())
            {
                using (var channel = connection.CreateModel())
                {
                    channel.ExchangeDeclare(exchange: mExChange, type: ExchangeType.Fanout);

                    channel.QueueDeclare(queue: mQueueName, durable: false, exclusive: false, autoDelete: false, arguments: null);
                    channel.QueueBind(queue: mQueueName, exchange: mExChange, routingKey: mRoutingKey, arguments: null);

                    var consumer = new EventingBasicConsumer(channel);
                    consumer.Received += (model, ea) =>
                    {
                        var body = ea.Body.ToArray();
                        var message = Encoding.UTF8.GetString(body);
                        action?.Invoke(message);

                        //手动签收，可以降低每次签收的性能损耗
                        channel.BasicAck(ea.DeliveryTag, false);
                    };
                    channel.BasicConsume(queue: mQueueName,
                                         autoAck: false,
                                         consumer: consumer);
                    Console.ReadLine();
                }
            }
        }

        public static void SendDirect(string msg)
        {
            using (var connection = Mq.GetConnect())
            {
                using (var channel = connection.CreateModel())
                {
                    channel.ExchangeDeclare(exchange: mExChange, type: ExchangeType.Direct);

                    channel.QueueDeclare(queue: mQueueName, durable: false, exclusive: false, autoDelete: false, arguments: null);
                    channel.QueueBind(queue: mQueueName, exchange: mExChange, routingKey: mRoutingKey, arguments: null);

                    var message = GetMsgByte(msg);
                    channel.BasicPublish(exchange: mExChange,
                                         routingKey: mRoutingKey,
                                         basicProperties: null,
                                         body: message);
                    Console.ReadLine();

                }
            }
        }

        public static void ReceiveDirect(Action<string> action)
        {
            using (var connection = Mq.GetConnect())
            {
                using (var channel = connection.CreateModel())
                {
                    channel.ExchangeDeclare(exchange: mExChange, type: ExchangeType.Direct);

                    channel.QueueDeclare(queue: mQueueName, durable: false, exclusive: false, autoDelete: false, arguments: null);
                    channel.QueueBind(queue: mQueueName, exchange: mExChange, routingKey: mRoutingKey, arguments: null);

                    var consumer = new EventingBasicConsumer(channel);
                    consumer.Received += (model, ea) =>
                    {
                        var body = ea.Body.ToArray();
                        var message = Encoding.UTF8.GetString(body);
                        action?.Invoke(message);

                        //手动签收，可以降低每次签收的性能损耗
                        channel.BasicAck(ea.DeliveryTag, false);
                    };
                    channel.BasicConsume(queue: mQueueName,
                                         autoAck: false,
                                         consumer: consumer);
                    Console.ReadLine();
                }
            }
        }

        public static void SendTopic(string msg)
        {
            using (var connection = Mq.GetConnect())
            {
                using (var channel = connection.CreateModel())
                {
                    channel.ExchangeDeclare(exchange: mExChange, type: ExchangeType.Topic);

                    var myQueue = channel.QueueDeclare(queue: mQueueName, durable: false, exclusive: false, autoDelete: false, arguments: null);
                    channel.QueueBind(queue: mQueueName, exchange: mExChange, routingKey: mRoutingKey, arguments: null);

                    var message = GetMsgByte(msg);
                    channel.BasicPublish(exchange: mExChange,
                                         routingKey: mRoutingKey,
                                         basicProperties: null,
                                         body: message);
                }
            }
        }

        public static void ReceiveTopic(Action<string> action)
        {
            using (var connection = Mq.GetConnect())
            {
                using (var channel = connection.CreateModel())
                {
                    channel.ExchangeDeclare(exchange: mExChange, type: ExchangeType.Topic);

                    channel.QueueDeclare(queue: mQueueName, durable: false, exclusive: false, autoDelete: false, arguments: null);
                    channel.QueueBind(queue: mQueueName, exchange: mExChange, routingKey: mRoutingKey, arguments: null);

                    var consumer = new EventingBasicConsumer(channel);
                    consumer.Received += (model, ea) =>
                    {
                        var body = ea.Body.ToArray();
                        var message = Encoding.UTF8.GetString(body);
                        action?.Invoke(message);

                        //手动签收，可以降低每次签收的性能损耗
                        channel.BasicAck(ea.DeliveryTag, false);
                    };
                    channel.BasicConsume(queue: mQueueName,
                                         autoAck: false,
                                         consumer: consumer);
                    Console.ReadLine();
                }
            }
        }

        #endregion

    }
}
